#include <SGE.h>
using namespace SGE;

#include "Bullet.h"
#include "Enemy.h"
#include "Fighter.h"

Fighter fighter;

const int kMaxBullets = 100;
Bullet bullets[kMaxBullets];
int bulletIndex = 0;

const int kMaxEnemies = 100;
Enemy enemies[kMaxEnemies];
int enemyIndex = 0;

const int kMaxExplosions = 100;
SGE_Emitter explosions[kMaxExplosions];
int explosionIndex = 0;

SGE_Sprite background;
SGE_Sound fireSound;
SGE_Sound explosionSound;

float spawnDelay = 0.0f;
bool quit = false;

void UpdateGameObjects(float deltaTime)
{
	fighter.Update(deltaTime);
	for (int i = 0; i < kMaxBullets; ++i)
	{
		bullets[i].Update(deltaTime);
	}
	for (int i = 0; i < kMaxEnemies; ++i)
	{
		enemies[i].Update(deltaTime);
	}
	for (int i = 0; i < kMaxExplosions; ++i)
	{
		explosions[i].Update(deltaTime);
	}
}

void FireBullets()
{
	if (Input_IsKeyPressed(Keys::SPACE))
	{
		const int index0 = bulletIndex;
		const int index1 = (bulletIndex + 1) % kMaxBullets;
		const int index2 = (bulletIndex + 2) % kMaxBullets;
		if (!bullets[index0].IsActive() &&
			!bullets[index1].IsActive() &&
			!bullets[index2].IsActive())
		{
			SVector2 pos = fighter.GetPosition();
			SVector2 pos0(pos.x - 20.0f, pos.y);
			SVector2 pos1(pos.x,         pos.y);
			SVector2 pos2(pos.x + 20.0f, pos.y);
			SVector2 vel0(-100.0f, -500.0f);
			SVector2 vel1( 0.0f,   -500.0f);
			SVector2 vel2( 100.0f, -500.0f);
			bullets[index0].Fire(pos0, vel0);
			bullets[index1].Fire(pos1, vel1);
			bullets[index2].Fire(pos2, vel2);
			bulletIndex = (index2 + 1) % kMaxBullets;

			fireSound.Play();
		}
	}
}

void SpawnEnemies(float deltaTime)
{
	spawnDelay -= deltaTime;
	if (spawnDelay <= 0.0f)
	{
		// It's time to spawn!
		if (!enemies[enemyIndex].IsActive())
		{
			const int kWinWidth = IniFile_GetInt("WinWidth", 800);
			const float posX = kWinWidth * RandomFloat(0.1f, 0.9f);
			const float posY = -100.0f;
			enemies[enemyIndex].Spawn(SVector2(posX, posY));
			enemyIndex = (enemyIndex + 1) % kMaxEnemies;

			// Reset delay time
			spawnDelay = RandomFloat(0.1f, 0.5f);
		}
	}
}

void CheckCollision()
{
	for (int e = 0; e < kMaxEnemies; ++e)
	{
		if (enemies[e].IsActive())
		{
			for (int b = 0; b < kMaxBullets; ++b)
			{
				if (bullets[b].IsActive())
				{
					SCircle eCircle = enemies[e].GetBoundingCircle();
					SCircle bCircle = bullets[b].GetBoundingCircle();
					//float xDiff = eCircle.center.x - bCircle.center.x;
					//float yDiff = eCircle.center.y - bCircle.center.y;
					//float dist = sqrt(xDiff * xDiff + yDiff * yDiff);
					//float radii = eCircle.radius + bCircle.radius;
					//if (dist <= radii)
					if (Intersect(eCircle, bCircle))
					{
						enemies[e].Kill();
						bullets[b].Kill();

						explosions[explosionIndex].SetPosition(eCircle.center);
						explosions[explosionIndex].Start(100.0f, true);
						explosionIndex = (explosionIndex + 1) % kMaxExplosions;

						explosionSound.Play();
						break;
					}
				}
			}
		}
	}
}

void SGE_Initialize()
{
	fighter.Load();
	
	const int kWinWidth = IniFile_GetInt("WinWidth", 800);
	const int kWinHeight = IniFile_GetInt("WinHeight", 600);
	SVector2 startPosition(kWinWidth * 0.5f, kWinHeight * 0.75f);
	fighter.SetPosition(startPosition);

	for (int i = 0; i < kMaxBullets; ++i)
	{
		bullets[i].Load();
	}

	for (int i = 0; i < kMaxEnemies; ++i)
	{
		enemies[i].Load();
	}

	for (int i = 0; i < kMaxExplosions; ++i)
	{
		explosions[i].Load("explosion.txt");
	}

	background.Load("space.jpg");
	fireSound.Load("photongun1.wav");
	explosionSound.Load("explosion.wav");
}

void SGE_Terminate()
{
	fighter.Unload();

	for (int i = 0; i < kMaxBullets; ++i)
	{
		bullets[i].Unload();
	}

	for (int i = 0; i < kMaxEnemies; ++i)
	{
		enemies[i].Unload();
	}

	for (int i = 0; i < kMaxExplosions; ++i)
	{
		explosions[i].Unload();
	}
	
	background.Unload();
	fireSound.Unload();
	explosionSound.Unload();
}

bool SGE_Update(float deltaTime)
{
	UpdateGameObjects(deltaTime);
	FireBullets();
	SpawnEnemies(deltaTime);
	CheckCollision();

	if (Input_IsKeyPressed(Keys::ESCAPE))
	{
		quit = true;
	}
	return quit;
}

void SGE_Render()
{
	background.Render();

	for (int i = 0; i < kMaxEnemies; ++i)
	{
		enemies[i].Render();
	}

	for (int i = 0; i < kMaxBullets; ++i)
	{
		bullets[i].Render();
	}

	fighter.Render();

	for (int i = 0; i < kMaxExplosions; ++i)
	{
		explosions[i].Render(true);
	}
}